package fr.hotel.services;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import fr.hotel.bo.Client;
import fr.hotel.bo.affinite.Affinite;
import fr.hotel.bo.affinite.Bruit;
import fr.hotel.bo.affinite.Chaleur;
import fr.hotel.bo.affinite.Humidite;
import fr.hotel.bo.affinite.Nourriture;
import fr.hotel.bo.affinite.Odeur;
import fr.hotel.bo.affinite.Voisinnage;
import fr.hotel.constantes.IConstantes;
import fr.hotel.xml.ParserXML;

public class ServiceClient {

	private Document clientXML;

	public List<Client> construction(String fichierClient)
			throws ParserConfigurationException, SAXException, IOException {
		List<Client> clients = new ArrayList<Client>();
		clientXML = ParserXML.parserDocument(fichierClient);

		NodeList clientsXML = clientXML
				.getElementsByTagName(IConstantes.CLT_CLIENT);
		int id = 1;
		for (int i = 0; i < clientsXML.getLength(); i++) {
			Node clientNode = clientsXML.item(i);
			Client client = creationClient(clientNode);
			client.setId(id++);
			clients.add(client);
		}
		return clients;
	}

	private Client creationClient(Node clientNode) {
		Client client = new Client();
		NodeList infoClient = clientNode.getChildNodes();
		for (int i = 0; i < infoClient.getLength(); i++) {
			Node cli = infoClient.item(i);
			if (IConstantes.CLT_DEMANDE.equals(cli.getNodeName())) {
				setDemandeClient(client, cli.getFirstChild().getTextContent());
			} else if (IConstantes.CLT_DONNE.equals(cli.getNodeName())) {
				client.setDonne(getAffinite(cli.getFirstChild().getTextContent()));
			}
		}
		return client;
	}

	private Affinite getAffinite(String textContent) {
		if (IConstantes.BRUIT.equals(textContent)) {
			return new Bruit();
		} else if (IConstantes.CHALEUR.equals(textContent)) {
			return new Chaleur();
		} else if (IConstantes.HUMIDITE.equals(textContent)) {
			return new Humidite();
		} else if (IConstantes.NOURRITURE.equals(textContent)) {
			return new Nourriture();
		} else if (IConstantes.ODEUR.equals(textContent)) {
			return new Odeur();
		} else {
			return new Voisinnage();
		}
	}

	private void setDemandeClient(Client client, String contenu) {
		String signe = contenu.substring(0, 1);
		String cont = contenu.substring(1);
		String value = (signe.equals("+")) ? "1" : "-1";
		if (cont.equals(IConstantes.BRUIT)) {
			if (client.getAffinite1() == null) {
				client.setAffinite1(new Bruit(value));
			} else
				client.setAffinite2(new Bruit(value));
		} else if (cont.equals(IConstantes.CHALEUR)) {
			if (client.getAffinite1() == null) {
				client.setAffinite1(new Chaleur(value));
			} else
				client.setAffinite2(new Chaleur(value));
		} else if (cont.equals(IConstantes.HUMIDITE)) {
			if (client.getAffinite1() == null) {
				client.setAffinite1(new Humidite(value));
			} else
				client.setAffinite2(new Humidite(value));
		} else if (cont.equals(IConstantes.NOURRITURE)) {
			if (client.getAffinite1() == null) {
				client.setAffinite1(new Nourriture(value));
			} else
				client.setAffinite2(new Nourriture(value));
		} else if (cont.equals(IConstantes.ODEUR)) {
			if (client.getAffinite1() == null) {
				client.setAffinite1(new Odeur(value));
			} else
				client.setAffinite2(new Odeur(value));
		} else if (cont.equals(IConstantes.VOISINAGE)) {
			if (client.getAffinite1() == null) {
				client.setAffinite1(new Voisinnage(value));
			} else
				client.setAffinite2(new Voisinnage(value));
		}
	}

	public Map<String, List<Client>> getClientsParAffinite(
			List<Client> clients, Affinite affinite) {
		Map<String, List<Client>> toReturn = new HashMap<String, List<Client>>();
		List<Client> clientAffinite = new ArrayList<Client>();
		List<Client> clientNonAffinite = new ArrayList<Client>();
		List<Client> clientDonnee = new ArrayList<Client>();

		String affiniteNom = affinite.getClass().getName();

		for (Client client : clients) {
			String affinite1Nom = client.getAffinite1().getClass().getName();
			String affinite2Nom = client.getAffinite2().getClass().getName();
			String donneeNom = client.getDonne().getClass().getName();
			if ((affiniteNom.equals(affinite1Nom) && client.getAffinite1()
					.getAffinite().equals("1"))
					|| (affiniteNom.equals(affinite2Nom) && client
							.getAffinite2().getAffinite().equals("1"))) {
				clientAffinite.add(client);
			} else if ((affiniteNom.equals(affinite1Nom) && client.getAffinite1()
					.getAffinite().equals("-1"))
					|| (affiniteNom.equals(affinite2Nom) && client
							.getAffinite2().getAffinite().equals("-1"))) {
				clientNonAffinite.add(client);
			}
			
			if (affiniteNom.equals(donneeNom)) {
				clientDonnee.add(client);
			}
			
		}
		toReturn.put("aime", clientAffinite);
		toReturn.put("nonaime", clientNonAffinite);
		toReturn.put("donnee", clientDonnee);
		return toReturn;
	}

}
